package com.ultrapower.charts.delaunay
{
	import de.polygonal.ds.Collection;
	import de.polygonal.ds.Iterator;
	
	
/**
 * A Triangle is an immutable Set of exactly three Pnts.
 *
 * All Set operations are available. Individual vertices can be accessed via
 * iterator() and also via triangle.get(index).
 *
 * Note that, even if two triangles have the same vertex set, they are
 * *different* triangles. Methods equals() and hashCode() are consistent with
 * this rule.
 *
 * @author Paul Chew
 *
 * Created December 2007. Replaced general simplices with geometric triangle.
 *
 * Translated to AS3 version by lwz7512, in Sep 2008.
 */
	
	
	
	public class Triangle extends ArraySet
	{
		private var idNumber:int;                   // The id number
	    private var circumcenter:Pnt = null;        // The triangle's circumcenter
	
	    private static var idGenerator:int = 0;     // Used to create id numbers
	    public static var moreInfo:Boolean = false; // True iff more info in toString


		/**
         * @param vertices the vertices of the Triangle.
     	 * @throws IllegalArgumentException if there are not three distinct vertices
     	 */
		public function Triangle(col:Collection)
		{
			super(col);
			idNumber = idGenerator++;
	        if (this.size != 3){
	        	throw new Error("Triangle must have 3 vertices");
	        }
	            
		}
		
	    override public function toString ():String {
	        if (!moreInfo) return "Triangle" + idNumber;
	        return "Triangle" + idNumber + super.toString();
	    }
	
	    /**
	     * Get arbitrary vertex of this triangle, but not any of the bad vertices.
	     * @param badVertices one or more bad vertices
	     * @return a vertex of this triangle, but not one of the bad vertices
	     * @throws NoSuchElementException if no vertex found
	     */
	    public function getVertexButNot (... badVertices):Pnt {
	    	var target:Pnt
	    	
	    	var triPnt:Array = this.toArray();
	    	var pntIterator:Iterator = this.iterator;
	        while(pntIterator.hasNext()){
	        	var v:Pnt = pntIterator.next() as Pnt;
	        	var foundIt:Boolean = false;
	        	for each(var bad:Pnt in badVertices){
	        		if(bad == v){	        			
	        			foundIt = true;
	        			break;	        			
	        		}
	        	}
	        	if(!foundIt){
	        		target = v;
	        		break;
	        	}
				
	        }
	        if(target==null){
	        	throw new Error("No vertex found");
	        } 
	        return target;
	    }
	    
		
	    /**
	     * True iff triangles are neighbors. Two triangles are neighbors if they
	     * share a facet.
	     * @param triangle the other Triangle
	     * @return true iff this Triangle is a neighbor of triangle
	     */	    
	    public function isNeighbor (triangle:Triangle):Boolean {
	        var count:int = 0;	
	        var thisIterator:Iterator = this.iterator;
	        while(thisIterator.hasNext()){
	        	var vertex:Pnt = thisIterator.next() as Pnt;
	        	if (!triangle.contains(vertex)) count++;
	        }       	        
	        return count == 1;
	    }
	
	    /**
	     * Report the facet opposite vertex.
	     * @param vertex a vertex of this Triangle
	     * @return the facet opposite vertex
	     * @throws IllegalArgumentException if the vertex is not in triangle
	     */
	    public function facetOpposite (vertex:Pnt):ArraySet {
	    	var facet:ArraySet = new ArraySet(this);
	    	var result:Boolean = facet.removeItem(vertex);
	        if (!result){
	        	throw new Error("Vertex not in triangle");
	        }	           
	        return facet;
	    }
	
	    /**
	     * @return the triangle's circumcenter
	     */
	    public function getCircumcenter ():Pnt {
	        if (circumcenter == null)
	            circumcenter = Pnt.circumcenter(this.toArray());
	        return circumcenter;
	    }
	
	    /* The following two methods ensure that a Triangle is immutable */
	
	    public function add (vertex:Pnt):Boolean {
	        throw new Error("UnsupportedOperationException");
	    }
	
	   
	
	    /* The following two methods ensure that all triangles are different. */
	    public function hashCode ():int {
	        return (idNumber^(idNumber>>>32));
	    }
	
	    public function equals (o:Object):Boolean {
	        return (this == o);
	    }

		public function get id():int{
			return idNumber;
		}
		
		
	}//end of Triangel
}